#include "BaseThread/BaseThread.h"
#include <stdio.h>
#include "Log/Log.h"
#include "Poco/Clock.h"

using namespace std;

BaseThread::BaseThread(bool bUseEvent)
{
    m_bRunning = false;
    m_bUseEvent = bUseEvent;
}

void BaseThread::Start()
{
    try
    {
        if (m_bRunning)
        {
            return;
        }
        m_bRunning = true;
        m_thread.start(*this);
    }
    catch (Poco::Exception & ec)
    {
        zlog.SError("%s catched, className [%s] code [%d] displayText [%s] message [%s] name [%s] what [%s]\n", __PRETTY_FUNCTION__, ec.className(), ec.code(), ec.displayText().c_str(), ec.message().c_str(), ec.name(), ec.what());
    }
    catch (...)
    {
        zlog.SError("%s catched\n", __PRETTY_FUNCTION__);
    }
}

void BaseThread::Stop()
{
    try
    {
        zlog.SInfo("%s in\n", __PRETTY_FUNCTION__);
        if (m_bRunning == false)
        {
            return;
        }
        m_bRunning = false;
        m_thread.join(10 * 1000);
    }
    catch (Poco::Exception & ec)
    {
        zlog.SError("%s catched, className [%s] code [%d] displayText [%s] message [%s] name [%s] what [%s]\n", __PRETTY_FUNCTION__, ec.className(), ec.code(), ec.displayText().c_str(), ec.message().c_str(), ec.name(), ec.what());
    }
    catch (...)
    {
        zlog.SError("%s catched\n", __PRETTY_FUNCTION__);
    }
}

bool BaseThread::IsRunning()
{
    return m_bRunning && m_thread.isRunning();
}

void BaseThread::SetEvent()
{
    m_event.set();
}

int BaseThread::WaitStop(int iTimeOut)
{
    Poco::Clock clk;
    while (clk.elapsed() < iTimeOut * 1000 * 1000)
    {
        if (IsRunning() == false)
        {
            zlog.SInfo("%s stop with %lld ms\n", __PRETTY_FUNCTION__, clk.elapsed() / 1000);
            return 0;
        }
        Poco::Thread::sleep(100);
    }
    zlog.SInfo("%s timeout\n", __PRETTY_FUNCTION__);
    return -1;
}

void BaseThread::run()
{
    while (m_bRunning)
    {
        int iMs = 0;
        try
        {
            if (m_bUseEvent)
            {
                m_event.wait();
            }
            iMs = SingleStep();
        }
        catch (...)
        {
            iMs = -1;
        }

        if (iMs >= 0)
        {
            Poco::Thread::sleep(iMs);
        }
        else if (iMs == NextLoop_Exit)
        {
            m_bRunning = false;
            break;
        }
        else if (iMs == NextLoop_UseEvent && m_bUseEvent)
        {
            continue;
        }
        else
        {
            m_bRunning = false;
            zlog.SError("%s invalid return value [%d]\n", __PRETTY_FUNCTION__, iMs);
            break;
        }
    }
}
